package com.houweishi.module.adjustment.service.impl;

import com.alibaba.fastjson.JSON;
import com.houweishi.common.constant.Constants;
import com.houweishi.common.constant.HttpStatus;
import com.houweishi.common.core.domain.AjaxResult;
import com.houweishi.common.core.domain.entity.SysUser;
import com.houweishi.common.core.domain.model.LoginUser;
import com.houweishi.common.exception.base.BaseException;
import com.houweishi.common.utils.DateUtils;
import com.houweishi.common.utils.SecurityUtils;
import com.houweishi.module.adjustment.domain.OaAdjustment;
import com.houweishi.module.adjustment.domain.OaAdjustmentApproval;
import com.houweishi.module.adjustment.mapper.OaAdjustmentMapper;
import com.houweishi.module.adjustment.service.IOaAdjustmentService;
import com.houweishi.module.bizSerialNum.service.IBizSerialNumTService;
import com.houweishi.module.copy.domain.BizCopy;
import com.houweishi.module.copy.mapper.BizCopyMapper;
import com.houweishi.module.record.domain.BizApprovalRecord;
import com.houweishi.module.record.mapper.BizApprovalRecordMapper;
import com.houweishi.module.record.service.IBizApprovalRecordService;
import com.houweishi.system.mapper.SysUserMapper;
import com.houweishi.ws.po.Message;
import com.houweishi.ws.service.WebSocketServer;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 职位，薪资申请单Service业务层处理
 * 
 * @author houweishi
 * @date 2023-02-21
 */
@Service
public class OaAdjustmentServiceImpl implements IOaAdjustmentService
{
    private static final Logger LOGGER = LoggerFactory.getLogger(OaAdjustmentServiceImpl.class);
//    @Autowired
    @Resource
    private OaAdjustmentMapper oaAdjustmentMapper;

    @Resource
    private BizApprovalRecordMapper bizApprovalRecordMapper;

    /**
     * 生成流水单号Service
     */
    @Resource
    private IBizSerialNumTService iBizSerialNumTService;

    @Resource
    private SysUserMapper sysUserMapper;

    @Resource
    private BizCopyMapper bizCopyMapper;

    /**
     * 消息推送Server
     */
    @Autowired
    private WebSocketServer webSocketServer;

    /**
     * 审批记录Service
     */
    @Resource
    private IBizApprovalRecordService iBizApprovalRecordService;


    /**
     * 查询职位，薪资申请单
     * 
     * @param adjustmentId 职位，薪资申请单主键
     * @return 职位，薪资申请单
     */
    @Override
    public OaAdjustment selectOaAdjustmentByAdjustmentId(Long adjustmentId)
    {
        OaAdjustment oaAdjustment = oaAdjustmentMapper.selectOaAdjustmentByAdjustmentId(adjustmentId);
        //根据条件查询审批记录列表
        selectApprovalRecordList(oaAdjustment);
        return oaAdjustment;
    }

    /**
     * 查询职位，薪资申请单列表
     * 
     * @param oaAdjustment 职位，薪资申请单
     * @return 职位，薪资申请单
     */
    @Override
    public List<OaAdjustment> selectOaAdjustmentList(OaAdjustment oaAdjustment)
    {
        List<OaAdjustment> oaAdjustmentList = oaAdjustmentMapper.selectOaAdjustmentList(oaAdjustment);

        if(!CollectionUtils.isEmpty(oaAdjustmentList)){
            oaAdjustmentList.forEach(adjustment->{
                //根据条件查询审批记录列表
                selectApprovalRecordList(adjustment);
            });
        }
        return oaAdjustmentMapper.selectOaAdjustmentList(oaAdjustment);
    }

    /**
     * 查询职位，薪资申请单列表（含业务表审批状态）
     *
     * @param oaAdjustment 职位，薪资申请单
     * @return 职位，薪资申请单
     */
    @Override
    public List<OaAdjustmentApproval> selectOaAdjustmentApprovalList(OaAdjustment oaAdjustment) {
        return oaAdjustmentMapper.selectOaAdjustmentApprovalList(oaAdjustment);
    }


    /**
     * 新增职位，薪资申请单
     * 
     * @param oaAdjustment 职位，薪资申请单
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult insertOaAdjustment(OaAdjustment oaAdjustment)
    {
        //获取当前人
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (loginUser==null){
            return new AjaxResult(HttpStatus.UNAUTHORIZED,"请先登录");
        }
        //判断是否再提交
        if(StringUtils.isNotBlank(oaAdjustment.getSerialNum())){
            oaAdjustment.setUpdateTime(DateUtils.parseDate(DateUtils.getTime()));
            oaAdjustment.setUpdateBy(loginUser.getUsername());
            //修改报销单，审批记录表，抄送
            return resubmitReimburse(oaAdjustment,loginUser);
        }else{
            //获取流水单号
            String serialNum = iBizSerialNumTService.generateSerialNum("ZWXZ");
            oaAdjustment.setSerialNum(serialNum);
            oaAdjustment.setUpdateTime(DateUtils.parseDate(DateUtils.getTime()));
            oaAdjustment.setUpdateBy(loginUser.getUsername());
            oaAdjustment.setCreateBy(loginUser.getUsername());
            oaAdjustment.setCreateTime(DateUtils.parseDate(DateUtils.getTime()));

            int result = oaAdjustmentMapper.insertOaAdjustment(oaAdjustment);
            if (result<1){
                return new AjaxResult(HttpStatus.ERROR,"新增职位，薪资申请单失败");
            }
            //插入审批记录表
            return setApprovalRecord(oaAdjustment,loginUser);
        }

    }


    /**
     * 重提交：修改职位，薪资申请，审批记录表，抄送
     * @param oaAdjustment
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult resubmitReimburse(OaAdjustment oaAdjustment,LoginUser loginUser) {
        //修改报销单
        oaAdjustmentMapper.updateOaAdjustment(oaAdjustment);
        //删除审批记录
        bizApprovalRecordMapper.deleteBizApprovalRecordBySerialNum(oaAdjustment.getSerialNum());
        // 删除抄送
        bizCopyMapper.deleteBizCopyMapperBySerialNum(oaAdjustment.getSerialNum());
        //新增审批及抄送
        return setApprovalRecord(oaAdjustment,loginUser);
    }


    /**
     * 修改职位，薪资申请单
     * 
     * @param oaAdjustment 职位，薪资申请单
     * @return 结果
     */
    @Override
    public int updateOaAdjustment(OaAdjustment oaAdjustment)
    {
        oaAdjustment.setUpdateTime(DateUtils.getNowDate());
        //先删后增
        oaAdjustmentMapper.deleteBizApprovalRecord(oaAdjustment);
        //插入审批记录表
        setApprovalRecord(oaAdjustment,null);
        return oaAdjustmentMapper.updateOaAdjustment(oaAdjustment);
    }

    /**
     * 批量删除职位，薪资申请单
     * 
     * @param adjustmentIds 需要删除的职位，薪资申请单主键
     * @return 结果
     */
    @Override
    public int deleteOaAdjustmentByAdjustmentIds(Long[] adjustmentIds)
    {
        return oaAdjustmentMapper.deleteOaAdjustmentByAdjustmentIds(adjustmentIds);
    }

    /**
     * 删除职位，薪资申请单信息
     * 
     * @param adjustmentId 职位，薪资申请单主键
     * @return 结果
     */
    @Override
    public int deleteOaAdjustmentByAdjustmentId(Long adjustmentId)
    {
        return oaAdjustmentMapper.deleteOaAdjustmentByAdjustmentId(adjustmentId);
    }




    /**
     * 根据条件查询审批记录列表
     * @param oaAdjustment
     */
    void selectApprovalRecordList(OaAdjustment oaAdjustment){
        //三个条件定位准确的数据(申请）
        BizApprovalRecord bizApprovalRecord = new BizApprovalRecord();
        bizApprovalRecord.setApplicationId(oaAdjustment.getAdjustmentId());
        bizApprovalRecord.setUserId(oaAdjustment.getUserId());
        bizApprovalRecord.setSubscribePatternId(oaAdjustment.getSubscribePatternId());

        List<BizApprovalRecord> list = bizApprovalRecordMapper.selectBizApprovalRecordList(bizApprovalRecord);
        oaAdjustment.setApprovalRecordList(list);

        //三个条件定位准确的数据（抄送）
        BizCopy bizCopy = new BizCopy() ;
        bizCopy.setApplicationId(oaAdjustment.getAdjustmentId());
        bizCopy.setUserId(oaAdjustment.getUserId());
        bizCopy.setSubscribePatternId(oaAdjustment.getSubscribePatternId());

        List<BizCopy> list2 = bizCopyMapper.selectBizCopyList(bizCopy);
        oaAdjustment.setBizCopyList(list2);
    }

    /**
     * 插入审批记录表和抄送记录表
     * @param oaAdjustment
     */
    @Transactional(rollbackFor = Exception.class)
    AjaxResult setApprovalRecord(OaAdjustment oaAdjustment, LoginUser loginUser) {
        List<BizApprovalRecord> list;
        if ("0".equals(oaAdjustment.getTypeStatus())){
            list= iBizApprovalRecordService.approvalTemplate(loginUser,oaAdjustment.getSerialNum(),"调薪");
        }else{
            list=addApprovalRecord(oaAdjustment,loginUser);
        }
        bizApprovalRecordMapper.insertBatchBizApprovalRecord(list);
        //增加抄送人
        addCopyPeople(oaAdjustment);
        // 推送消息
        List<BizApprovalRecord> messageList = list.stream()
                .filter(a -> a.getSequence() == 2)
                .collect(Collectors.toList());
        sendMessage(messageList.get(0).getApproverId(), messageList.get(0).getApproverName(), oaAdjustment);
        return new AjaxResult(HttpStatus.SUCCESS, "新增职位，薪资调整审批记录成功");
    }

    /**
     * 不使用模板，自定义
     * @param oaAdjustment
     * @param loginUser
     * @return
     */
    public List<BizApprovalRecord> addApprovalRecord(OaAdjustment oaAdjustment, LoginUser loginUser){
        List<BizApprovalRecord> list = new ArrayList<>();
        int sequence = 1;
        //保存发起人
        BizApprovalRecord initiatorRecord = createApprovalRecord(oaAdjustment, null, loginUser);
        initiatorRecord.setSequence(sequence);
        initiatorRecord.setSerialNum(oaAdjustment.getSerialNum());
        initiatorRecord.setApprovalStatus(Constants.COMPLETED);
        initiatorRecord.setTypeOperation(Constants.AGREE);
        initiatorRecord.setBusinessStatus(Constants.APPROVE);
        list.add(initiatorRecord);
        //字符串分割，并把String[]转换为list(传入了一个字符串类型的数据）
        if (StringUtils.isEmpty(oaAdjustment.getApprover())) {
            throw new BaseException("请选择新增职位，薪资调整审批人");
        }
        String[] approvers = oaAdjustment.getApprover().split(",");
        List<Long> idList = Arrays.stream(approvers).map(s -> Long.parseLong(s.trim())).collect(Collectors.toList());
        //获取详细审批人信息
        List<SysUser> sysUserList = sysUserMapper.selectUserByUserIds(idList);
        if (idList.size() != sysUserList.size()) {
            throw new BaseException("新增职位，薪资调整审批人有误");
        }
        //根据职位级别降级排序
        sysUserList.sort(Comparator.comparingLong(SysUser::getPositionLevel).reversed());

        //增加审批记录
        if (!CollectionUtils.isEmpty(sysUserList)) {
            for (int i = 0; i < sysUserList.size(); i++) {
                SysUser sysUser = sysUserMapper.selectUserById(sysUserList.get(i).getUserId());
                BizApprovalRecord approvalRecord = createApprovalRecord(oaAdjustment, sysUser, null);
                if (i == 0) {
                    approvalRecord.setApprovalStatus(Constants.APPROVE);
                } else {
                    approvalRecord.setApprovalStatus(Constants.NOT_APPROVED);
                }
                sequence++;
                approvalRecord.setSequence(sequence);
                list.add(approvalRecord);
            }
        }
        return list;
    }

    /**
     * 推送消息到前端
     * @param userId
     * @param userName
     * @param oaAdjustment
     */
    private void sendMessage(Long userId, String userName, OaAdjustment oaAdjustment) {
        try {
            //发送消息
            Message message = new Message();
            message.setFromId(oaAdjustment.getUserId());
            message.setFromName(oaAdjustment.getUsername());
            message.setNextNodeId(userId);
            message.setNextNodeName(userName);
            message.setStatus(Constants.COMPLETED);
            message.setSerialNum(oaAdjustment.getSerialNum());
            message.setType(oaAdjustment.getSubscribePatternName());
            webSocketServer.onMessage(JSON.toJSONString(message));
        } catch (Exception e) {
            LOGGER.error("职位，薪资调整消息推送失败",e);
        }
    }

    /**
     * 设置审批记录信息
     * @param oaAdjustment
     * @param sysUser
     * @return
     */
    public BizApprovalRecord createApprovalRecord(OaAdjustment oaAdjustment, SysUser sysUser, LoginUser loginUser) {
        BizApprovalRecord bizApprovalRecord = new BizApprovalRecord();
        if (null != sysUser){
            bizApprovalRecord.setApproverId(sysUser.getUserId());
            bizApprovalRecord.setApproverName(sysUser.getUserName());
            bizApprovalRecord.setPositionLevel(sysUser.getPositionLevel());
        }
        if (null !=loginUser){
            bizApprovalRecord.setApproverId(loginUser.getUserId());
            bizApprovalRecord.setApproverName(loginUser.getUsername());
        }
        bizApprovalRecord.setSubscribePatternName("调薪");
        bizApprovalRecord.setSerialNum(oaAdjustment.getSerialNum());
        bizApprovalRecord.setApplicationId(oaAdjustment.getAdjustmentId());
        bizApprovalRecord.setUserId(oaAdjustment.getUserId());
        bizApprovalRecord.setUsername(oaAdjustment.getUsername());
        bizApprovalRecord.setSubscribePatternId(oaAdjustment.getSubscribePatternId());
        bizApprovalRecord.setSubscribePatternName(oaAdjustment.getSubscribePatternName());
        bizApprovalRecord.setUpdateTime(DateUtils.parseDate(DateUtils.getTime()));
        bizApprovalRecord.setUpdateBy(oaAdjustment.getUsername());
        bizApprovalRecord.setCreateBy(oaAdjustment.getUsername());
        bizApprovalRecord.setCreateTime(DateUtils.parseDate(DateUtils.getTime()));
        return bizApprovalRecord;
    }

    /**
     * 添加抄送人
     * @param oaAdjustment
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public void addCopyPeople(OaAdjustment oaAdjustment) {
        if (StringUtils.isNoneBlank(oaAdjustment.getCopyerId())){
            //字符串分割，并把String[]转换为list，（抄送人id）
            String[] copyerIds = oaAdjustment.getCopyerId().split(",");
            List<String> copyerIdList = Arrays.stream(copyerIds).collect(Collectors.toList()) ;
            //抄送记录表
            if(!CollectionUtils.isEmpty(copyerIdList)){
                copyerIdList.forEach(id->{
                    BizCopy bizCopy = new BizCopy();
                    SysUser sysUser = sysUserMapper.selectUserById(Long.valueOf(id));

                    bizCopy.setApplicationId(oaAdjustment.getAdjustmentId());
                    bizCopy.setCopyerId(sysUser.getUserId());
                    bizCopy.setCopyerName(sysUser.getUserName());
                    bizCopy.setPositionLevel(sysUser.getPositionLevel());
                    bizCopy.setUserId(oaAdjustment.getUserId());
                    bizCopy.setUsername(oaAdjustment.getUsername());
                    bizCopy.setSubscribePatternId(oaAdjustment.getSubscribePatternId());
                    bizCopy.setSubscribePatternName(oaAdjustment.getSubscribePatternName());
                    bizCopy.setSerialNum(oaAdjustment.getSerialNum());
                    bizCopy.setCopyerStatus("0");
                    bizCopy.setCreateTime(DateUtils.getNowDate());
                    bizCopyMapper.insertBizCopy(bizCopy);
                });
            }
        }
    }
}
